﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;
using System.ComponentModel;
using System.Collections;
using System.ComponentModel.Design;
using System.Drawing.Design;

namespace TR0217.ControlEx
{
    [ToolboxBitmap(typeof(ComboBoxEx), "ComboBoxEx.bmp")]
    public class ColorComboBox:ComboBox
    {
        public ColorComboBox():base()
        {
            base.DrawMode = DrawMode.OwnerDrawFixed;
            base.DropDownStyle = ComboBoxStyle.DropDownList;
        }

        [Editor(typeof(ColorComboBoxItemCollectionEditor), typeof(UITypeEditor))]
        public new ObjectCollection Items
        {
            get { return base.Items; }
        }

        [Browsable(false)]
        public new ComboBoxStyle DropDownStyle
        {
            get { return base.DropDownStyle; }
            set { ;}
        }

        [Browsable(false)]
        public new DrawMode DrawMode
        {
            get { return base.DrawMode; }
            set { ;}
        }

        public Color SelectedColor
        {
            get 
            {
                if (base.SelectedItem != null)
                {
                    ColorComboBoxItem item = base.SelectedItem as ColorComboBoxItem;
                    if (item != null)
                    {
                        return item.Color;
                    }                    
                }
                return  Color.White; 
            }
            set
            {
                int i = this.FindMostLikeItem(value);
                if ( i < 0)
                {
                    i = 0;
                    ColorComboBoxItem item = new ColorComboBoxItem(value);
                    base.Items.Insert(0, item);   
                }
                this.SelectedIndex = i;
            }
        }

        private int FindMostLikeItem(Color value)
        {
            HSLColor hslColor = new HSLColor(value);
            int ret = -1;
            for (int i = 0; i < base.Items.Count; i++)
            {
                ColorComboBoxItem item = base.Items[i] as ColorComboBoxItem;
                if (item != null && !item.ColorIndicate)
                {
                    if (Math.Abs(item.HSLColor.Hue - hslColor.Hue) < 2.0)
                    {
                        return i;
                    }
                    else if ((item.HSLColor.Lightness > 0.998765))
                    {
                        return i;
                    }
                }
            }
            return ret;
        }

        private int FindItem(Color value)
        {
            int ret = -1;
            for (int i = 0; i < base.Items.Count; i++)
            {
                ColorComboBoxItem item = base.Items[i] as ColorComboBoxItem;
                if (item != null && !item.ColorIndicate && item.Color == value)
                {
                    return i;
                }
            }
            return ret;
        }

        protected override void OnCreateControl()
        {
            base.OnCreateControl();
        }

        protected override void OnDrawItem(DrawItemEventArgs e)
        {
            StringFormat format = new StringFormat();
            Brush fbrush = new SolidBrush(e.ForeColor);
            format.FormatFlags = StringFormatFlags.NoClip;
            RectangleF itemRect = new RectangleF(e.Bounds.X, e.Bounds.Top + 1, e.Bounds.Width, e.Bounds.Height-2);

            e.DrawBackground();
            if (e.Index < 0)
            {
                e.Graphics.DrawString(this.Text, this.Font, fbrush, itemRect, format);
            }
            else
            {
                ColorComboBoxItem item = base.Items[e.Index] as ColorComboBoxItem;
                if (item != null)
                {
                    if (!item.ColorIndicate)
                    {
                        Brush cbursh = new SolidBrush(item.Color);
                        e.Graphics.FillRectangle(cbursh, itemRect);
                        cbursh.Dispose();
                    }
                }
                e.Graphics.DrawString(base.Items[e.Index].ToString(), e.Font, fbrush, itemRect, format);
            }

            fbrush.Dispose();
            format.Dispose();
        }

        protected override void OnSelectedIndexChanged(EventArgs e)
        {
            base.OnSelectedIndexChanged(e);
            if (base.SelectedIndex < 0) return;
            ColorComboBoxItem item = base.Items[base.SelectedIndex] as ColorComboBoxItem;
            if (item != null)
            {
                if (item.ColorIndicate)
                {
                    int i = base.SelectedIndex - 1;
                    i = i < 0 ? 0 : i;
                    ColorPickerDialog dlgColorPicker = ColorPickerDialog.Instance;
                    if (dlgColorPicker.ShowDialog() == DialogResult.OK)
                    {
                        item = new ColorComboBoxItem();
                        item.Color = dlgColorPicker.SelectedColor;
                        base.Items.Insert(i, item);                        
                    }
                    base.SelectedIndex = i;
                }
            }
        }

    }

    public class ColorComboBoxItem
    {
        Color _color;

        public System.Drawing.Color Color
        {
            get { return _color; }
            set { _color = value; }
        }

        HSLColor _hslColor;
        public TR0217.ControlEx.HSLColor HSLColor
        {
            get { return _hslColor; }
            set { _hslColor = value; }
        }

        string _text = string.Empty;
        public string Text
        {
            get { return _text; }
            set { _text = value; }
        }

        bool _colorIndicate = false;
        public bool ColorIndicate
        {
            get { return _colorIndicate; }
            set { _colorIndicate = value; }
        }

        public ColorComboBoxItem()
        {

        }

        public ColorComboBoxItem(string text)
        {
            _text = text;
            _colorIndicate = true;
        }

        public ColorComboBoxItem(Color color)
        {
            _color = color;
            _hslColor = new HSLColor(_color);
        }

        public ColorComboBoxItem(Color color, string text)
        {
            _color = color;
            _hslColor = new HSLColor(_color);
            _text = text;
        }

        public override string ToString()
        {
            return _text;
        }
    }

    public class ColorComboBoxItemCollectionEditor : CollectionEditor
    {
        public ColorComboBoxItemCollectionEditor(Type type)
            : base(type)
        {
        }

        protected override bool CanSelectMultipleInstances()
        {
            return false;
        }

        protected override Type CreateCollectionItemType()
        {
            return typeof(ColorComboBoxItem);
        }
    }
}
